SWAGOLX.EXE (c) 1993 GDSOFT ALL RIGHTS RESERVED 00007 1 08-24-9413:29ALL ERIC LOWE Re Cpu-intensive RoutineSWAG9408 ╔Qº╓ 6 └╫ {πI'm looking for a SMALL piece of code which can be used to replace a DELAYπcommand that will be cpu-intensive, meaning that it will execute more quickπdepending upon the type of cpu and clock speed. I know that obviously anyπcode will exhibit this tendency, but I'm looking for something which do soπa most dramatic fashion (as far as speed goes). It should also be ratherπsmall and not necessarily zeroing in on the presence of an FPU. Any ideas?π}ππProcedure CPUDelay(D: Word); Assembler;πasmπ @@1:π mov cx,$FFFFπ @@2:π nopπ loop @@2π dec[d]π jnz @@1πend;π 2 08-24-9413:45ALL DAVE JARVIS Machine Model Byte SWAG9408 +^1 5 └╫ πVARπ Model : BYTE ABSOLUTE $F000:$FFFE; ππBEGIN π CASE Model OF π $9A : WriteLn( 'COMPAQ Plus' ); π $FF : WriteLn( 'IBM PC' ); π $FE : WriteLn( 'PC XT, Portable PC' ); π $FD : WriteLn( 'PCjr' );ππ $FC : WriteLn( 'Personal Computer AT, PS/2 Models 50 and 60' ); π $FB : WriteLn( 'PC XT (after 1/10/86)' ); π $FA : WriteLn( 'PS/2 Model 30' ); π $F9 : WriteLn( 'Convertible PC' ); π $F8 : WriteLn( 'PS/2 Model 80' ); π End; πEND.π 3 08-24-9413:58ALL MAYNARD PHILBROOK Cpu & Speed SWAG9408 │¡kd 17 └╫ {π SM> Does anyone have any code to tell me WHAT KIND of CPU isπ SM> installed on a computer, and how fast the CPU is?? I'm using TP 6.0.π SM> Thanks! Also, while I'm at it, how about some code to detect if aπ SM> co-processor is installed (Optional) Thanks!π SM> -!-ππ well here is somthing i used to get a scale for the Delay command i haveπ in my drop in replacement CRT Unit, this will get a scale of the machineπ runing so that if the program gets run on different speed machines theπ code will analize it to produce the scale so DELAY will properly work onπ different machines.ππ the speed is a Word Variable i use in the normal area of pascalππ my 486 sx priduces aprox 39,450 at 33Mhz, when 8 mhz is runing it willπ produce aprox 10,500..π So with that i think you can figure out somthing..π}ππVARπ Speed : WORD;ππBEGINππAsmπ STIπ Mov AX, $0040;π Mov ES, AX;π Mov Bl, [ES:$006c]; { Get jiffy clock current value }π And BL, $01; { monitor bit 0 only }π Xor AX, AX; { with need a 48 bit reference for fast machines }π Xor DX, DX; { clear AX, DX, SI }π Xor SI, SI;π { the following is to syncronize the clock to insure that we are atπ starting of a new clock count }π@lp:π Mov BH, [ES:$006c]; { Now get the jiffy again }π and BH, $01; { only need to check bit }π cmp BL,BH; { if clock is still the same then it has incremented }π Je @lp;π { Now we know the clock at the start of a new timing cycle }π@Lp1:π Inc AX; { Increment 48 bit counters now }π Jnz @lp2;π Inc DX;π Jz @lp2;π Inc SI;π@Lp2:π Mov BH, [ES:$006c];π And BH, $01;π Cmp BL, BH;π Jne @Lp1; { Loop back increment counters until jiffy bit 0 changes }π SHR SI,1; { now we scale down the 48 bits into a 16 bit reference }π RCR DX,1;π RCR AX,1;π SHR DX,1;ππ RCR AX,1; { if you need more resolution then exclude one of then RCR,SHR}π SHR DX,1; { you would also need to use DX reg of you do as the 32 bit }ππ RCR AX,1;π SHR AX,1;ππ Mov Speed,AX; { Set Scale Factor }πEnd;ππWriteLn(Speed);ππEND.π 4 08-25-9409:05ALL PETER VAN DER LANDEN CMOS reading SWAG9408 ╜H%> 27 └╫ {πFrom: landen@cir.frg.eur.nl (Peter van der Landen)ππ>I am attempting to write a program in TP6.0 that reads the CMOS memoryπ>(IBM PC) and saves the settings to a disk file. I know there are 255π>locations, but I don't know where. If someone could point me to theπ>correct memory addresses, I'd really appreciate it. Thanks (in advance)!ππThis unit (by an unknown other) shows you how it's done. The CMOS memory isπnot part of the PC's main memory. Values are written/read by accessing anπI/O port.ππ}πunit CMOS;ππInterfaceππconstπ ClockSec = $00; { RTclock seconds }π ClockMin = $02; { RTclock minutes }π ClockHour = $04; { RTclock hours }π ClockDOW = $06; { RTclock day of week }π ClockDay = $07; { RTclock day in month }π ClockMon = $08; { RTclock month }π ClockYear = $09; { RTclock year (mod 100)}π AlarmSec = $01; { Alarm seconds }π AlarmMin = $03; { Alarm minutes }π AlarmHour = $05; { Alarm hours }π Diskettes = $10; { Floppy disk type byte }π HardDisk = $12; { Regular hard disk type }π HDExt1 = $19; { Extended hard disk type, unit 1 }π HDExt2 = $1A; { Extended hard disk type, unit 2 }π Equipment = $14; { Equipment list }π CheckLo = $2F; { Checksum low }π CheckHi = $2E; { Checksum high }π BaseLo = $15; { Base mem low }π BaseHi = $16; { Base mem high }π ExpdLo = $17; { Expansion mem size low }π ExpdHi = $18; { Expansion mem size high }π StatRegA = $0A; { Status Register A }π StatRegB = $0B; { Status register B }π StatRegC = $0C; { Status register C }π StatRegD = $0D; { Status register D }π DiagStat = $0E; { Diagnostic status byte }π ShutDown = $0F; { Shutdown status byte }π Century = $32; { BCD Century number }π AltExpdLo = $30; { Expansion mem size low (alternate) }π AltExpdHi = $31; { Expansion mem size high (alternate) }π InfoFlags = $33; { Bit 7 set = top 128k installed, bitπ 6 set = first user message (?) }ππfunction ReadCmos(Address: byte): byte;π { Returns the byte at the given CMOS ADDRESS }ππprocedure WriteCmos(Address, Data: byte);π { Writes DATA to ADDRESS in CMOS ram }ππprocedure SetCMOSCheckSum;π { Sets the CMOS checksum after you've messed with it :-}ππ{ The following bytes are RESERVED: $11, $13, $1B-$2D, andπ $34-$3F ($3F marks the end of the CMOS area). You'll note thatπ some of these are included in the checksum calculation. }ππimplementationππconstπ CmosAddr = $70; { CMOS control port }π CmosData = $71; { CMOS data port }ππfunction ReadCmos(Address: byte): byte;πbeginπ port[CmosAddr] := Address;π ReadCmos := port[CmosData]πend; {ReadCmos}ππprocedure WriteCmos(Address, Data: byte);πbeginπ port[CmosAddr] := Address;π port[CmosData] := Dataπyend; {WriteCmos}ππprocedure SetCMOSCheckSum;π{ The checksum is simply the sum of $10 to $2D π (some of these bytes are reserved) }ππvarπ I, Sum: word;πbeginπ Sum := 0;π for I:= $10 to $2D do Sum := Sum + ReadCmos(I);π WriteCmos(CheckHi, Hi(sum));π WriteCmos(CheckLo, Lo(sum));πend; {SetCMOSCheckSum}ππend.π 5 08-25-9409:06ALL TERJE MATHISEN Processor Speed IndependeSWAG9408 &4s 16 └╫ {πFrom: terjem@hda.hydro.com (Terje Mathisen)ππ>I need the source code to (in TP and/or Assembly) setup a processorπ>independant delay. The one I have is way faster on a 486 than on a 386.π>I need something that tests the machines speed when a unit is initializedπ>and saves a number to a variable and then a delay procedure that usesπ>that number.ππWell, the Delay() procedure in the Crt unit is designed to do exactly this,πbut if you cannot use Crt, try this replacement which I wrote almostπ10 years ago, and later converted to a Unit.π}ππ{$R-,S-}πUnit Delays;ππINTERFACEππCONST loop_count : WORD = 250;ππPROCEDURE Delay(ms : WORD);ππIMPLEMENTATIONππPROCEDURE Delay(ms : Word);πBEGINπInline(π $8B/$76/<MS { mov si,[bp<ms]}π /$09/$F6 { or si,si}π /$74/$09 { jz d2}π /$8B/$0E/>LOOP_COUNT {d0: mov cx,[>loop_count]}π /$E2/$FE {d1: loop d1}π /$4E { dec si}π /$75/$F7 { jnz d0}π); {d2:}πEND;ππBEGINπInLine(π $B8/$40/$00 { mov ax,$40}π /$8E/$C0 { mov es,ax}π /$BB/$6C/$00 { mov bx,$6C}π /$26/$8B/$37 {d3: es: mov si,[bx]}π /$31/$FF { xor di,di}π /$26/$3B/$37 {d4: es: cmp si,[bx]}π /$74/$FB { je d4}π /$26/$8B/$37 { es: mov si,[bx]}π /$8B/$0E/>LOOP_COUNT {d5: mov cx,[>loop_count]}π /$E2/$FE {d6: loop d6}π /$47 { inc di}π /$26/$3B/$37 { es: cmp si,[bx]}π /$74/$F4 { je d5}π /$A1/>LOOP_COUNT { mov ax,[>loop_count]}π /$F7/$E7 { mul di}π /$B9/$37/$00 { mov cx,55}π /$F7/$F1 { div cx}π /$A3/>LOOP_COUNT { mov [>loop_count],ax}π /$81/$FF/$1E/$00 { cmp di,30}π /$72/$D4 { jb d3}π);πEND.ππ 6 08-25-9409:11ALL TIMO SALMI Rebooting PC SWAG9408 k¡(U 32 └╫ {π Q: How is the code for rebooting the PC written in Turbo Pascal?ππ A: This item draws from the information and the C-code example inπStan Brown's comp.os.msdos.programmer FAQ, garbo.uwasa.fi:π/pc/doc-net/faqp9317.zip (at the time of writing this), fromπmemory.lst and interrup.b in /pc/programming/inter39b.zip, and fromπ/pc/programming/helppc21.zip. The Turbo Pascal code is my adaptationπof the C-code. It is not a one-to-one replica.π The usually advocated warm-boot method is storing $1234 in theπword at $0040:$0072 and jumping to address $FFFF:$0000. The problemπwith this approach is that files must first be closed, potentialπcaches flushed. This is how to do thisπ}ππ procedure REBOOT;π label next;π var regs : registers;π i : byte;π ticks : longint;π beginπ {... "press" alt-ctrl ...}π mem[$0040:$0017] := mem[$0040:$0017] or $0C; { 00001100 }π {... "press" del, try a few times ...}π for i := 1 to 10 doπ beginπ FillChar (regs, sizeOf(regs), 0); { initialize }π regs.ah := $4F; { service number }π regs.al := $53; { del key's scan code }π regs.flags := FCarry; { "sentinel for ignoring key" }π Intr ($15, regs);π {... check if the del key registered, if not retry ...}π if regs.flags and Fcarry > 0 then goto next;π {... waste some time, watch out for midnight ...}π ticks := MemL [$0040:$006C];π repeat until (MemL[$0040:$006C] - ticks > 3) orπ (MemL[$0040:$006C] - ticks < 0)π end; {for}π exit;π next:π {... disk reset: writes all modified disk buffers to disk ...}π FillChar (regs, sizeOf(regs), 0);π regs.ah := $0D;π MsDos (regs);π {... set post-reset flag, use $0000 instead of $1234 for coldboot ...}π memW[$0040:$0072] := $1234;π {... jump to $FFFF:0000 BIOS reset ...}π Inline($EA/$00/$00/$FF/$FF);π end; (* reboot *)π{πOne slight problem with this approach is that the keyboard interceptπinterrupt $15 service $4F requires at least an AT according toπinter39b.zip. A simple test based on "FFFF:E byte ROM machine id"π(the previous definition is from helppc21.zip) is:π}π function ISATFN : boolean;π beginπ case Mem[$F000:$FFFE] ofπ $FC, $FA, $F8 : isatfn := true;π else isatfn := false;π end; {case}π end; (* isatfn *)π{πFor a more comprehensive test use CPUFN "Get the type of theπprocessor chip" from TSUNTH in garbo.uwasa.fi:/pc/ts/tspa*.zip orπsee the TP + ASM code in Michael Ticher (1992), PC Intern SystemπProgramming, pp. 725-727.π An addition by Per Bergland (d6caps@dtek.chalmers.se): I recentlyπdownloaded the FAQ for this newsgroup, and studied the code forπrebooting a PC. The problem with that code (calling FFFF:0000) isπthat it will not work in protected mode programs such as thoseπcompiled for Windows or BP7 DPMI, or even in a DOS program run in aπWindows DOS session. The solution provided has been tested onπvarious COMPAQ PC:s, but I think it will work on any AT-classπmachine. It involves using the 8042 keyboard controller chip outputπpin 0, which is physically connected to the reset pin of the CPU.πThere is unfortunately no way to perform a "warm" reboot this way,πand the warnings about disk caches etc apply to this code, too (seeπFAQ). The code is written in BP7 assembly lingo, because that's whatπI normally write code in, but anyone could rewrite it in C or highπlevel Pascal.π}ππ UNIT Reboot;π INTERFACEπ procedure DoReboot;π IMPLEMENTATIONπ procedure DoReboot;assembler;π asmπ cliπ @@WaitOutReady: { Busy-wait until 8042 is ready for new command}π in al,64h { read 8042 status byte}π test al,00000010b { Bit 1 of status indicates input buffer full }π jnz @@WaitOutReadyπ mov al,0FEh { Pulse "reset" = 8042 pin 0 }π out 64h,alπ { The PC will reboot now }π end;π END.π 7 08-26-9407:26ALL COLIN NICHOLSON Math Co-Processor Speed SWAG9408 ╒7╒' 13 └╫ {πHere is a program I wrote to see how good my new 387sx co-processor was. Itπuses the standard REAL type.π}πprogram Math_Speed_Test;π{$N-,E-,R-,S-}ππuses dos;ππvar i : longint;π num1, num2, num3 : real; { or double }π output : text;π hou,minu,seco,s100 : word;π StartClock,π StopClock : Real;ππProcedure ClockOn;ππBeginπ GetTime(hou,minu,seco,s100);π StartClock:=( hou * 3600 ) + ( minu * 60 ) + seco + ( s100 / 100 );πEnd;ππProcedure ClockOff;πππBeginπ GetTime(hou,minu,seco,s100);π StopClock:=( hou * 3600 ) + ( minu * 60 ) + seco + ( s100 / 100 );π WriteLn(output,'Elapsed Time = ',(StopClock-StartClock):0:2,'s');πEnd;πππbeginπ assign(output,'');π rewrite(output);π clockon;π{$IFOPT N+}π writeln(output,'Using 8087 Code');π{$ELSE}π writeln(output,'Using Software floating point routines');π{$ENDIF}π for i:=1 to 100000 doπ beginππ num1:=random(60000)/100;π repeatπ num2:=random(60000)/100;π until num2>0;π num3:=num1/num2;ππ end;π clockoff;π close(output);ππend.ππAnd the results.....ππUsing Software floating point routinesπElapsed Time = 31.03sππUsing 8087 CodeπElapsed Time = 8.78sππHowever, changing REAL to DOUBLE givesππUsing 8087 CodeπElapsed Time = 5.50sππI don't want to remove my co-processor, so I can't get the results forπusing the emulation library :-). You could compile the program and try itπfor yourself.ππ